home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / proc / procMisc.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  51KB  |  1,934 lines

  1. /*
  2.  *  procMisc.c --
  3.  *
  4.  *    Misc. routines to get and set process state.
  5.  *
  6.  * Copyright 1986 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/proc/procMisc.c,v 9.26 92/09/27 15:50:49 shirriff Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <proc.h>
  22. #include <status.h>
  23. #include <sync.h>
  24. #include <sched.h>
  25. #include <sig.h>
  26. #include <stdlib.h>
  27. #include <list.h>
  28. #include <string.h>
  29. #include <procInt.h>
  30. #include <rpc.h>
  31. #include <dbg.h>
  32. #include <vm.h>
  33. #include <ctype.h>
  34. #include <fscache.h>
  35. #include <fsutil.h>
  36. #include <rpcClient.h>
  37. #include <rpcServer.h>
  38. #include <procServer.h>
  39. #include <fsrmt.h>
  40. #include <lfsTypes.h>
  41. #include <fsconsist.h>
  42. #include <bstring.h>
  43. #include <stdio.h>
  44.  
  45. #define min(a,b) ((a) < (b) ? (a) : (b))
  46. /*
  47.  * Procedures internal to this file
  48.  */
  49.  
  50. static ReturnStatus     GetRemotePCB _ARGS_((int hostID, Proc_PID pid,
  51.                 Proc_PCBInfo *pcbPtr, char *argString));
  52. static void        FillPCBInfo _ARGS_((Proc_ControlBlock *pcbPtr,
  53.                 Proc_PCBInfo *statusInfoPtr));    
  54.  
  55. /*
  56.  *----------------------------------------------------------------------
  57.  *
  58.  * Proc_Init --
  59.  *
  60.  *    Called during startup to initialize data structures.
  61.  *
  62.  * Results:
  63.  *    None.
  64.  *
  65.  * Side effects:
  66.  *    Process table initialized, debug list initialized, locks initialized.
  67.  *
  68.  *----------------------------------------------------------------------
  69.  */
  70.  
  71. void
  72. Proc_Init()
  73. {
  74.     ProcInitTable();
  75.     ProcDebugInit();
  76. }
  77.  
  78.  
  79. /*
  80.  *----------------------------------------------------------------------
  81.  *
  82.  * Proc_GetPCBInfo --
  83.  *
  84.  *    Returns the process control blocks for the specified processes
  85.  *    on the specified host.  If firstPid is equal to PROC_MY_PID
  86.  *    and the hostID is PROC_MY_HOSTID, then the PCB for the current
  87.  *    process is returned.  Otherwise PCBs for all processes in the
  88.  *    range firstPid to lastPid on host hostID are returned.  Only
  89.  *    the index portions of the processIDs for firstPid and lastPid
  90.  *    are relevant. 
  91.  *
  92.  * Results:
  93.  *    SYS_INVALID_ARG -     firstPid was < 0, firstPid > lastPid
  94.  *    SYS_ARG_NOACCESS -     The buffers to store the pcbs in were not
  95.  *                accessible.
  96.  *      *trueNumBuffers is set to be the actual number of
  97.  *    PCBs returned which can be less than the number requested if
  98.  *    lastPid - firstPid is greater than the maximum PCBs available.
  99.  *
  100.  * Side effects:
  101.  *    None.
  102.  *
  103.  *----------------------------------------------------------------------
  104.  */
  105.  
  106. /*
  107.  * Macro to fix up ticks for a process control block.
  108.  */
  109. #define TICKS_TO_TIME(pcbEntry) \
  110.     Timer_TicksToTime(pcbEntry.kernelCpuUsage.ticks,  \
  111.               &pcbEntry.kernelCpuUsage.time); \
  112.     Timer_TicksToTime(pcbEntry.userCpuUsage.ticks,  \
  113.               &pcbEntry.userCpuUsage.time); \
  114.     Timer_TicksToTime(pcbEntry.childKernelCpuUsage.ticks,  \
  115.               &pcbEntry.childKernelCpuUsage.time); \
  116.     Timer_TicksToTime(pcbEntry.childUserCpuUsage.ticks,  \
  117.               &pcbEntry.childUserCpuUsage.time);
  118.  
  119.  
  120. ReturnStatus
  121. Proc_GetPCBInfo(firstPid, lastPid, hostID, infoSize, bufferPtr, 
  122.         argsPtr, trueNumBuffersPtr)
  123.     Proc_PID         firstPid;         /* First pid to get info for. */
  124.     Proc_PID        lastPid;         /* Last pid to get info for. */
  125.     int            hostID;             /* Host ID to get info for. */
  126.     int            infoSize;            /* Size of structure */
  127.     Address         bufferPtr;         /* Pointer to buffers. */
  128.     Proc_PCBArgString    *argsPtr;         /* Pointer to argument strings. */
  129.     int         *trueNumBuffersPtr;  /* The actual number of buffers 
  130.                         used.*/
  131. {
  132.     register Proc_ControlBlock     *procPtr = (Proc_ControlBlock *) NIL;
  133.     int                i, j;
  134.     char             argString[PROC_PCB_ARG_LENGTH];
  135.     Proc_ControlBlock        pcbEntry;
  136.     Boolean            remote = FALSE;
  137.     Proc_PID            processID = firstPid;
  138.     ReturnStatus        status = SUCCESS;
  139.     Proc_PCBInfo        statusInfo;
  140.     int                bytesToCopy;
  141.  
  142.  
  143.     if (firstPid != PROC_MY_PID) {
  144.     firstPid &= PROC_INDEX_MASK;
  145.     lastPid &= PROC_INDEX_MASK;
  146.     if ((firstPid > lastPid) ||
  147.         ((firstPid == PROC_MY_PID) && hostID != PROC_MY_HOSTID)) {
  148.         return(GEN_INVALID_ARG);
  149.     }
  150.     }
  151.     if (bufferPtr == USER_NIL) {
  152.     return (SYS_ARG_NOACCESS);
  153.     }
  154.     if (hostID != PROC_MY_HOSTID &&
  155.     (hostID <= 0 || hostID > NET_NUM_SPRITE_HOSTS)) {
  156.     return(GEN_INVALID_ARG);
  157.     }
  158.  
  159.     bytesToCopy = min(sizeof(Proc_PCBInfo), infoSize);
  160.     /*
  161.      * Determine whether to get process table entries for this machine.
  162.      * Currently, the information for this machine is returned unless
  163.      * another machine is explicitly specified; i.e., migrated processes
  164.      * get information for their current machine rather than their home.
  165.      */
  166.  
  167.     if (hostID == PROC_MY_HOSTID) {
  168. #ifdef FORWARD_MIGRATED_GET_PCBS
  169.     procPtr = Proc_GetCurrentProc();
  170.     Proc_Lock(procPtr);
  171.     if (procPtr->genFlags & PROC_FOREIGN) {
  172.         hostID = procPtr->peerHostID;
  173.         processID = procPtr->peerHostID;
  174.         remote = TRUE;
  175.     } 
  176.     Proc_Unlock(procPtr);
  177. #endif /* FORWARD_MIGRATED_GET_PCBS */
  178.     } else if (hostID != rpc_SpriteID) {
  179.     remote = TRUE;
  180.     }
  181.  
  182.     if (firstPid == PROC_MY_PID) {
  183.     /*
  184.      *  Return PCB for the current process.
  185.      */
  186.     procPtr = Proc_GetCurrentProc();
  187.     if (!remote) {
  188.         bcopy((Address)procPtr, (Address)&pcbEntry,
  189.             sizeof (Proc_ControlBlock));
  190.         TICKS_TO_TIME(pcbEntry);
  191.         FillPCBInfo(&pcbEntry, &statusInfo);
  192.     } else {
  193.         status = GetRemotePCB(hostID, processID, &statusInfo,
  194.                        argString);
  195.         if (status != SUCCESS) {
  196.         return(status);
  197.         }
  198.     }
  199.     if (Proc_ByteCopy(FALSE, bytesToCopy,
  200.         (Address)&statusInfo, (Address) bufferPtr) != SUCCESS) {
  201.         return(SYS_ARG_NOACCESS);
  202.     }
  203.     if (argsPtr != (Proc_PCBArgString *) USER_NIL) {
  204.         if (!remote) {
  205.         if (procPtr->argString != (Address) NIL) {
  206.             (void) strncpy(argString, procPtr->argString,
  207.                 PROC_PCB_ARG_LENGTH - 1);
  208.             argString[PROC_PCB_ARG_LENGTH - 1] = '\0';
  209.         } else {
  210.             argString[0] = '\0';
  211.         }
  212.         }
  213.         if (Proc_ByteCopy(FALSE, PROC_PCB_ARG_LENGTH, argString,
  214.                   (Address) argsPtr) != SUCCESS) {
  215.         return(SYS_ARG_NOACCESS);
  216.         }
  217.     }
  218.     } else {
  219.     
  220.     /*
  221.      * Return PCB for all processes or enough to fill all of
  222.      * the buffers, whichever comes first.
  223.      */
  224.  
  225.     
  226.     for (i = firstPid, j = 0; 
  227.          i <= lastPid; 
  228.          i++, j++, (Address) bufferPtr += infoSize) {
  229.         if (!remote) {
  230.         if (i >= proc_MaxNumProcesses) {
  231.             break;
  232.         }
  233.         procPtr = Proc_GetPCB(i);
  234.         if (procPtr == (Proc_ControlBlock *) NIL) {
  235.             panic("Proc_GetInfo: procPtr == NIL!\n");
  236.             status = FAILURE;
  237.             break;
  238.         }
  239.         bcopy((Address)procPtr, (Address)&pcbEntry,
  240.             sizeof (Proc_ControlBlock));
  241.  
  242.         TICKS_TO_TIME(pcbEntry);
  243.         FillPCBInfo(&pcbEntry, &statusInfo);
  244.         } else {
  245.         status = GetRemotePCB(hostID, (Proc_PID) i, &statusInfo,
  246.                        argString);
  247.         if (status != SUCCESS) {
  248.             /*
  249.              * Break if we hit an error.  The typical error condition
  250.              * is to hit an invalid process ID, which happens since
  251.              * we don't know proc_MaxNumProcesses on the other
  252.              * machine.  Instead, we convert GEN_INVALID_ARG to
  253.              * SUCCESS and return what we found so far.
  254.              */
  255.             if (status == GEN_INVALID_ARG) {
  256.             status = SUCCESS;
  257.             }
  258.             break;
  259.         }
  260.         }
  261.         if (Proc_ByteCopy(FALSE, bytesToCopy,
  262.             (Address)&statusInfo, (Address) bufferPtr) != SUCCESS) {
  263.         return(SYS_ARG_NOACCESS);
  264.         }
  265.         if (argsPtr != (Proc_PCBArgString *) USER_NIL) {
  266.         if (!remote) {
  267.             if (procPtr->argString != (Address) NIL) {
  268.             (void) strncpy(argString, procPtr->argString,
  269.                        PROC_PCB_ARG_LENGTH - 1);
  270.             argString[PROC_PCB_ARG_LENGTH - 1] = '\0';
  271.             } else {
  272.             argString[0] = '\0';
  273.             }
  274.         }
  275.         if (Proc_ByteCopy(FALSE, PROC_PCB_ARG_LENGTH, argString,
  276.                   (Address) &(argsPtr[j])) != SUCCESS) {
  277.             return(SYS_ARG_NOACCESS);
  278.         }
  279.         }
  280.     }
  281.  
  282.     if (trueNumBuffersPtr != USER_NIL) {
  283.         if (Proc_ByteCopy(FALSE, sizeof(j), (Address) &j, 
  284.                 (Address) trueNumBuffersPtr) != SUCCESS) {
  285.         return(SYS_ARG_NOACCESS);
  286.         }
  287.     }
  288.     }
  289.  
  290.     return(status);
  291. }
  292.  
  293.  
  294.  
  295. /*
  296.  * Define some constants used to distinguish RPC sub-commands.
  297.  */
  298. #define GET_PCB 1
  299. #define GET_SEG_INFO 2
  300.  
  301. /*
  302.  *----------------------------------------------------------------------
  303.  *
  304.  * GetRemotePCB --
  305.  *
  306.  *    Perform an RPC to get a process control block from another host.
  307.  *
  308.  * Results:
  309.  *    The return status from the RPC is returned.  
  310.  *
  311.  * Side effects:
  312.  *    None.
  313.  *
  314.  *----------------------------------------------------------------------
  315.  */
  316.  
  317. static ReturnStatus    
  318. GetRemotePCB(hostID, pid, pcbPtr, argString)
  319.     int        hostID;        /* Host to send RPC to. */
  320.     Proc_PID    pid;        /* index of PCB to obtain. */
  321.     Proc_PCBInfo *pcbPtr;    /* Place to return PCB data. */
  322.     char    *argString;    /* Place to return argument string. */
  323. {
  324.     Rpc_Storage        storage;
  325.     ReturnStatus     status;
  326.     int            request;
  327.  
  328.     request = GET_PCB;
  329.     storage.requestParamPtr = (Address)&request;
  330.     storage.requestParamSize = sizeof(request);
  331.     storage.requestDataPtr = (Address)&pid;
  332.     storage.requestDataSize = sizeof(Proc_PID);
  333.     storage.replyParamPtr = (Address)pcbPtr;
  334.     storage.replyParamSize = sizeof(Proc_PCBInfo);
  335.     storage.replyDataPtr = (Address)argString;
  336.     storage.replyDataSize = PROC_PCB_ARG_LENGTH;
  337.  
  338.     status = Rpc_Call(hostID, RPC_PROC_GETPCB, &storage);
  339.     if (status == SUCCESS && storage.replyDataSize == 0) {
  340.     argString[0] = '\0';
  341.     }
  342.     return(status);
  343.  
  344. }
  345. /*
  346.  *----------------------------------------------------------------------
  347.  *
  348.  * Proc_GetRemoteSegInfo --
  349.  *
  350.  *    Perform an RPC to get info for a VM segment control from another host.
  351.  *
  352.  * Results:
  353.  *    The return status from the RPC is returned.  
  354.  *
  355.  * Side effects:
  356.  *    None.
  357.  *
  358.  *----------------------------------------------------------------------
  359.  */
  360.  
  361. ReturnStatus    
  362. Proc_GetRemoteSegInfo(hostID, segNum, segInfoPtr)
  363.     int        hostID;        /* Host to send RPC to. */
  364.     int        segNum;        /* index of segment to obtain. */
  365.     Vm_SegmentInfo *segInfoPtr;    /* Place to return segment data. */
  366. {
  367.     Rpc_Storage        storage;
  368.     ReturnStatus     status;
  369.     int            request;
  370.  
  371.     request = GET_SEG_INFO;
  372.     storage.requestParamPtr = (Address)&request;
  373.     storage.requestParamSize = sizeof(request);
  374.     storage.requestDataPtr = (Address)&segNum;
  375.     storage.requestDataSize = sizeof(int);
  376.     storage.replyParamPtr = (Address)segInfoPtr;
  377.     storage.replyParamSize = sizeof(Vm_SegmentInfo);
  378.     storage.replyDataPtr = (Address)NIL;
  379.     storage.replyDataSize = 0;
  380.  
  381.     status = Rpc_Call(hostID, RPC_PROC_GETPCB, &storage);
  382.     return(status);
  383.  
  384. }
  385.  
  386. /*
  387.  *----------------------------------------------------------------------
  388.  *
  389.  * FillPCBInfo --
  390.  *
  391.  *    Fills in a Proc_PCBInfo structure from the contents of a
  392.  *    control block.
  393.  *
  394.  * Results:
  395.  *    None.
  396.  *
  397.  * Side effects:
  398.  *    None.
  399.  *
  400.  *----------------------------------------------------------------------
  401.  */
  402.  
  403. static void
  404. FillPCBInfo(pcbPtr, statusInfoPtr)
  405.     Proc_ControlBlock        *pcbPtr;     /* Ptr to pcb to convert */
  406.     Proc_PCBInfo        *statusInfoPtr; /* Structure to fill in */
  407. {
  408.     int     i;
  409.  
  410.     statusInfoPtr->processor = pcbPtr->processor;
  411.     statusInfoPtr->state = pcbPtr->state;
  412.     statusInfoPtr->genFlags = pcbPtr->genFlags;
  413.     statusInfoPtr->processID = pcbPtr->processID;
  414.     statusInfoPtr->parentID = pcbPtr->parentID;
  415.     statusInfoPtr->familyID = pcbPtr->familyID;
  416.     statusInfoPtr->userID = pcbPtr->userID;
  417.     statusInfoPtr->effectiveUserID = pcbPtr->effectiveUserID;
  418.     statusInfoPtr->event = pcbPtr->event;
  419.     statusInfoPtr->billingRate = pcbPtr->billingRate;
  420.     statusInfoPtr->recentUsage = pcbPtr->recentUsage;
  421.     statusInfoPtr->weightedUsage = pcbPtr->weightedUsage;
  422.     statusInfoPtr->unweightedUsage = pcbPtr->unweightedUsage;
  423.     statusInfoPtr->kernelCpuUsage = pcbPtr->kernelCpuUsage.time;
  424.     statusInfoPtr->userCpuUsage = pcbPtr->userCpuUsage.time;
  425.     statusInfoPtr->childKernelCpuUsage = pcbPtr->childKernelCpuUsage.time;
  426.     statusInfoPtr->childUserCpuUsage = pcbPtr->childUserCpuUsage.time;
  427.     statusInfoPtr->numQuantumEnds = pcbPtr->numQuantumEnds;
  428.     statusInfoPtr->numWaitEvents = pcbPtr->numWaitEvents;
  429.     statusInfoPtr->schedQuantumTicks = pcbPtr->schedQuantumTicks;
  430.     for(i = 0; i < VM_NUM_SEGMENTS; i++) {
  431.     if (pcbPtr->vmPtr != (Vm_ProcInfo *) NIL && 
  432.         pcbPtr->vmPtr->segPtrArray[i] != (Vm_Segment *) NIL) {
  433.         statusInfoPtr->vmSegments[i] = 
  434.         (Vm_SegmentID) pcbPtr->vmPtr->segPtrArray[i]->segNum;
  435.     } else {
  436.         statusInfoPtr->vmSegments[i] = (Vm_SegmentID) -1;
  437.     }
  438.     }
  439.     statusInfoPtr->sigHoldMask = pcbPtr->sigHoldMask;
  440.     statusInfoPtr->sigPendingMask = pcbPtr->sigPendingMask;
  441.     for(i = 0; i < SIG_NUM_SIGNALS; i++) {
  442.     statusInfoPtr->sigActions[i] = pcbPtr->sigActions[i];
  443.     }
  444.     statusInfoPtr->peerHostID = pcbPtr->peerHostID;
  445.     statusInfoPtr->peerProcessID = pcbPtr->peerProcessID;
  446. }
  447.  
  448.  
  449. /*
  450.  *----------------------------------------------------------------------
  451.  *
  452.  * Proc_RpcGetPCB --
  453.  *
  454.  *    Stub to handle a remote request for a PCB or Vm_Segment.
  455.  *
  456.  * Results:
  457.  *    Status of reply:
  458.  *    GEN_INVALID_ARG - index into table of process control blocks is
  459.  *              invalid, or segment is invalid.
  460.  *    SUCCESS     - information is returned.
  461.  *
  462.  *    SUCCESS is passed to the caller on this machine.
  463.  *
  464.  * Side effects:
  465.  *    Reply is sent.
  466.  *
  467.  *----------------------------------------------------------------------
  468.  */
  469. /*ARGSUSED*/
  470. ReturnStatus    
  471. Proc_RpcGetPCB(srvToken, clientID, command, storagePtr)
  472.     ClientData          srvToken;    /* Handle on server process passed to
  473.                       * Rpc_Reply */
  474.     int          clientID;    /* Sprite ID of client host */
  475.     int          command;    /* Command identifier */
  476.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  477.                      * request buffers and also indicate 
  478.                      * the exact amount of data in the 
  479.                      * request buffers.  The reply fields 
  480.                      * are initialized to NIL for the
  481.                       * pointers and 0 for the lengths.  
  482.                      * This can be passed to Rpc_Reply */
  483. {
  484.     ReturnStatus    status = SUCCESS;
  485.     Proc_PID        *pidPtr;
  486.     Rpc_ReplyMem    *replyMemPtr;
  487.     Proc_PCBInfo    *pcbPtr;
  488.     Proc_ControlBlock   *procPtr = (Proc_ControlBlock *) NIL;
  489.     Proc_ControlBlock   pcb;
  490.     int            *segNumPtr;
  491.     Vm_SegmentInfo    *segInfoPtr;
  492.     int            *requestPtr;
  493.  
  494.     requestPtr = (int *) storagePtr->requestParamPtr;
  495.     if (*requestPtr == GET_SEG_INFO) {
  496.     segNumPtr = (int *) storagePtr->requestDataPtr;
  497.     segInfoPtr = (Vm_SegmentInfo *) malloc(sizeof (Vm_SegmentInfo));
  498.     status = Vm_EncapSegInfo(*segNumPtr, segInfoPtr);
  499.     storagePtr->replyParamPtr = (Address) segInfoPtr;
  500.     storagePtr->replyParamSize = sizeof(Vm_SegmentInfo);
  501.     goto done;
  502.     } else if (*requestPtr == GET_PCB) {
  503.     pidPtr = (Proc_PID *) storagePtr->requestDataPtr;
  504.     if (*pidPtr >= proc_MaxNumProcesses) {
  505.         status = GEN_INVALID_ARG;
  506.     } else {
  507.         procPtr = Proc_GetPCB(*pidPtr);
  508.         if (procPtr == (Proc_ControlBlock *) NIL) {
  509.         panic("Proc_RpcGetPCB: found nil PCB!");
  510.         status = FAILURE;
  511.         }
  512.     }
  513.     if (status != SUCCESS) {
  514.         Rpc_Reply(srvToken, status, storagePtr,
  515.               (int(*)())NIL, (ClientData)NIL);
  516.         return(SUCCESS);
  517.     }
  518.  
  519.     bcopy((Address) procPtr, (Address) &pcb, sizeof (Proc_ControlBlock));
  520.     TICKS_TO_TIME(pcb);
  521.     pcbPtr = (Proc_PCBInfo *) malloc(sizeof (Proc_PCBInfo));
  522.     storagePtr->replyParamPtr = (Address) pcbPtr;
  523.     storagePtr->replyParamSize = sizeof(Proc_PCBInfo);
  524.     FillPCBInfo(&pcb, pcbPtr);
  525.  
  526.     if (procPtr->argString != (Address) NIL) {
  527.         storagePtr->replyDataSize = strlen(procPtr->argString) + 1;
  528.         storagePtr->replyDataPtr = (Address) malloc(storagePtr->replyDataSize);
  529.         (void) strcpy(storagePtr->replyDataPtr, procPtr->argString);
  530.     } else {
  531.         storagePtr->replyDataSize = 0;
  532.         storagePtr->replyDataPtr = (Address) NIL;
  533.     }
  534.     }
  535.     done:
  536.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  537.     replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  538.     replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  539.  
  540.     Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  541.         (ClientData) replyMemPtr);
  542.     return(SUCCESS);
  543. }
  544.  
  545.  
  546. /*
  547.  *----------------------------------------------------------------------
  548.  *
  549.  * Proc_GetResUsage --
  550.  *
  551.  *    Returns the resource usage for a process.
  552.  *
  553.  * Results:
  554.  *    SYS_INVALID_ARG -     buffer address was invalid.
  555.  *    PROC_INVALID_PID -     The pid was out-of-range or specified a
  556.  *                non-existent process.
  557.  *    SYS_ARG_NOACCESS -     The buffers to store the pcbs in were not
  558.  *                accessible.
  559.  *
  560.  * Side effects:
  561.  *    None.
  562.  *
  563.  *----------------------------------------------------------------------
  564.  */
  565.  
  566. ReturnStatus
  567. Proc_GetResUsage(pid, bufferPtr)
  568.     Proc_PID         pid;
  569.     Proc_ResUsage     *bufferPtr;         
  570. {
  571.     register Proc_ControlBlock     *procPtr;
  572.     Proc_ResUsage         resUsage;         
  573.     ReturnStatus        status = SUCCESS;
  574.  
  575.     if (pid == PROC_MY_PID) {
  576.     procPtr = Proc_GetEffectiveProc();
  577.     if (procPtr == (Proc_ControlBlock *) NIL) {
  578.         panic("Proc_GetResUsage: procPtr == NIL\n");
  579.     } 
  580.     Proc_Lock(procPtr);
  581.     } else {
  582.     procPtr = Proc_LockPID(pid);
  583.         if (procPtr == (Proc_ControlBlock *) NIL) {
  584.             return (PROC_INVALID_PID);
  585.         }
  586.     }
  587.  
  588.     /*
  589.      *  Copy the information to the out parameters.
  590.      */
  591.  
  592.     if (bufferPtr == USER_NIL) {
  593.     status = SYS_INVALID_ARG;
  594.     } else {
  595.     Timer_TicksToTime(procPtr->kernelCpuUsage.ticks,
  596.               &resUsage.kernelCpuUsage);
  597.     Timer_TicksToTime(procPtr->userCpuUsage.ticks, &resUsage.userCpuUsage);
  598.     Timer_TicksToTime(procPtr->childKernelCpuUsage.ticks, 
  599.                 &resUsage.childKernelCpuUsage);
  600.     Timer_TicksToTime(procPtr->childUserCpuUsage.ticks,
  601.                 &resUsage.childUserCpuUsage);
  602.     resUsage.numQuantumEnds = procPtr->numQuantumEnds;
  603.     resUsage.numWaitEvents     = procPtr->numWaitEvents;
  604.  
  605.     if (Proc_ByteCopy(FALSE, sizeof(Proc_ResUsage), 
  606.         (Address) &resUsage, (Address) bufferPtr) != SUCCESS){
  607.         status = SYS_ARG_NOACCESS;
  608.     }
  609.     }
  610.     Proc_Unlock(procPtr);
  611.     return(status);
  612. }
  613.  
  614.  
  615. /*
  616.  *----------------------------------------------------------------------
  617.  *
  618.  * Proc_GetPriority --
  619.  *
  620.  *    Returns the priority of a process.
  621.  *
  622.  * Results:
  623.  *    SYS_INVALID_ARG -     priorityPtr address was invalid.
  624.  *    PROC_INVALID_PID -     The pid was out-of-range or specified a
  625.  *                non-existent process.
  626.  *    SYS_ARG_NOACCESS -     The buffer to store the priority was not
  627.  *                accessible.
  628.  *
  629.  * Side effects:
  630.  *    None.
  631.  *
  632.  *----------------------------------------------------------------------
  633.  */
  634.  
  635. ReturnStatus
  636. Proc_GetPriority(pid, priorityPtr)
  637.     Proc_PID pid;    /* ID of process whose priority is to be returned. */
  638.     int *priorityPtr;    /* Priority returned by Proc_GetPriority. */
  639. {
  640.     register Proc_ControlBlock     *procPtr;
  641.     ReturnStatus        status = SUCCESS;
  642.  
  643.     if (pid == PROC_MY_PID) {
  644.     procPtr = Proc_GetEffectiveProc();
  645.     if (procPtr == (Proc_ControlBlock *) NIL) {
  646.         panic("Proc_GetPriority: procPtr == NIL\n");
  647.     } 
  648.     Proc_Lock(procPtr);
  649.     } else {
  650.     procPtr = Proc_LockPID(pid);
  651.         if (procPtr == (Proc_ControlBlock *) NIL) {
  652.             return (PROC_INVALID_PID);
  653.         }
  654.     }
  655.  
  656.     /*
  657.      *  Copy the information to the out parameter.
  658.      */
  659.  
  660.     if (priorityPtr == USER_NIL) {
  661.     status = SYS_INVALID_ARG;
  662.     } else {
  663.     if (Proc_ByteCopy(FALSE, sizeof(int),
  664.              (Address) &(procPtr->billingRate),
  665.             (Address) priorityPtr) != SUCCESS) {
  666.         status = SYS_ARG_NOACCESS;
  667.     }
  668.     }
  669.     Proc_Unlock(procPtr);
  670.     return(status);
  671. }
  672.  
  673.  
  674. /*
  675.  *----------------------------------------------------------------------
  676.  *
  677.  * Proc_SetPriority --
  678.  *
  679.  *    Sets the priority for a process.
  680.  *
  681.  * Results:
  682.  *    PROC_INVALID_PID -     The pid was out-of-range or specified a
  683.  *                non-existent process.
  684.  *
  685.  * Side effects:
  686.  *    None.
  687.  *
  688.  *----------------------------------------------------------------------
  689.  */
  690.  
  691. ReturnStatus
  692. Proc_SetPriority(pid, priority, useFamily)
  693.     Proc_PID     pid;        /* ID of process whose priority is to be set. */
  694.     int     priority;    /* New scheduling priority for pid. */
  695.     Boolean     useFamily;    /* If TRUE, use pid as the head of a process 
  696.                  * family, and set the priority of every 
  697.                  * process in the family. */
  698. {
  699.     register Proc_ControlBlock     *procPtr;
  700.     register Proc_PCBLink    *procLinkPtr;
  701.     List_Links            *familyList;
  702.     int                userID;
  703.     ReturnStatus        status;
  704.  
  705.     if (priority > PROC_MAX_PRIORITY) {
  706.     priority = PROC_MAX_PRIORITY;
  707.     } else if (priority < PROC_MIN_PRIORITY) {
  708.     priority = PROC_MIN_PRIORITY;
  709.     }
  710.  
  711.     if (useFamily) {
  712.     /*
  713.      * Set priorities of processes in family.
  714.      */
  715.     status = Proc_LockFamily((int) pid, &familyList, &userID);
  716.     if (status != SUCCESS) {
  717.         return(status);
  718.     }
  719.     if (!Proc_HasPermission(userID)) {
  720.         Proc_UnlockFamily((int) pid);
  721.         return(PROC_UID_MISMATCH);
  722.     }
  723.     LIST_FORALL(familyList, (List_Links *) procLinkPtr) {
  724.         procPtr = procLinkPtr->procPtr;
  725.         Proc_Lock(procPtr);
  726.         procPtr->billingRate = priority;
  727.         Proc_Unlock(procPtr);
  728.     }
  729.     Proc_UnlockFamily((int) pid);
  730.     } else {
  731.     /*
  732.      * Set the individual process's priority.
  733.      */
  734.     if (pid == PROC_MY_PID) {
  735.         procPtr = Proc_GetEffectiveProc();
  736.         Proc_Lock(procPtr);
  737.     } else {
  738.         procPtr = Proc_LockPID(pid);
  739.         if (procPtr == (Proc_ControlBlock *) NIL) {
  740.         return (PROC_INVALID_PID);
  741.         }
  742.         if (!Proc_HasPermission(procPtr->effectiveUserID)) {
  743.         Proc_Unlock(procPtr);
  744.         return(PROC_UID_MISMATCH);
  745.         }
  746.     }
  747.     procPtr->billingRate = priority;
  748.     Proc_Unlock(procPtr);
  749.     }
  750.  
  751.     return(SUCCESS);
  752. }
  753.  
  754.  
  755. /*
  756.  *----------------------------------------------------------------------
  757.  *
  758.  * Proc_Profile --
  759.  *
  760.  *    Starts profiling the memory accesses of the current process.
  761.  *
  762.  * Results:
  763.  *    SUCCESS        -    always returned for now.
  764.  *
  765.  * Side effects:
  766.  *    None.
  767.  *
  768.  *----------------------------------------------------------------------
  769.  */
  770.  
  771. /*ARGSUSED*/
  772. ReturnStatus
  773. Proc_Profile(shiftSize, lowPC, highPC, interval, counterArray)
  774.     int shiftSize;    /* # of bits to shift the PC to the right. */
  775.     int lowPC;        /* The lowest PC to profile. */
  776.     int highPC;        /* The highest PC to profile. */
  777.     Time interval;    /* The time interval at which the PC is sampled. */
  778.     int counterArray[];    /* Counters used to count instruction executions. */
  779. {
  780.     return(SUCCESS);
  781. }
  782.  
  783.  
  784. /*
  785.  *----------------------------------------------------------------------
  786.  *
  787.  * Proc_Dump --
  788.  *
  789.  *    Prints out an abbreviated proc table for debugging purposes.
  790.  *
  791.  * Results:
  792.  *    SUCCESS.
  793.  *
  794.  * Side effects:
  795.  *    Prints stuff to screen.
  796.  *
  797.  *
  798.  *----------------------------------------------------------------------
  799.  */
  800.  
  801. ReturnStatus
  802. Proc_Dump()
  803. {
  804.     int i;
  805.     Proc_ControlBlock *pcbPtr;
  806.  
  807.     printf("\n%8s %5s %10s %10s %8s %8s   %s\n",
  808.     "ID", "wtd", "user", "kernel", "event", "state", "name");
  809.     
  810.     for (i = 0; i < proc_MaxNumProcesses; i++) {
  811.     pcbPtr = proc_PCBTable[i];
  812.     if (pcbPtr->state != PROC_UNUSED) {
  813.         Proc_DumpPCB(pcbPtr);
  814.     }
  815.     }
  816.     return(SUCCESS);
  817. }
  818.  
  819.  
  820. /*
  821.  *----------------------------------------------------------------------
  822.  *
  823.  * Proc_DumpPCB --
  824.  *
  825.  *    Prints out the contents of a PCB for debugging purposes.
  826.  *
  827.  * Results:
  828.  *    None.
  829.  *
  830.  * Side effects:
  831.  *    Prints stuff to the screen.
  832.  *
  833.  *----------------------------------------------------------------------
  834.  */
  835.  
  836. void
  837. Proc_DumpPCB(procPtr)
  838.     Proc_ControlBlock *procPtr;
  839. {
  840.  
  841.     Time    kernelTime, userTime;
  842.  
  843. #define DEBUG_INDEX    0x9
  844.  
  845.     static char *states[] = {
  846.     "unused",
  847.     "running",
  848.     "ready",
  849.     "waiting",
  850.     "exiting",
  851.     "dead",
  852.     "migrated",
  853.     "new",
  854.     "suspended",
  855.     "debug",
  856.     };
  857.     Proc_State state;
  858.  
  859.     state = procPtr->state;
  860.     switch (state) {
  861.     case PROC_UNUSED:
  862.     case PROC_RUNNING:
  863.     case PROC_READY:
  864.     case PROC_WAITING:
  865.     case PROC_EXITING:
  866.     case PROC_DEAD:
  867.     case PROC_MIGRATED:
  868.     case PROC_NEW:
  869.         break;
  870.     case PROC_SUSPENDED:
  871.         /* If process is suspended for debugging print "debug" for its
  872.          * state.
  873.          */
  874.         if (procPtr->genFlags & (PROC_DEBUGGED | PROC_ON_DEBUG_LIST)) {
  875.         state = (Proc_State)DEBUG_INDEX;
  876.         }
  877.         break;
  878.     default:
  879.         printf("Warning: Proc_DumpPCB: process %x has invalid process state: %x.\n",
  880.            procPtr->processID, state);
  881.         return;
  882.     }
  883.     /*
  884.      * A header describing the fields has already been printed.
  885.      */
  886.     Timer_TicksToTime(procPtr->userCpuUsage.ticks, &userTime);
  887.     Timer_TicksToTime(procPtr->kernelCpuUsage.ticks, &kernelTime);
  888.     printf("%8x %5d [%1d,%6d] [%1d,%6d] %8x %8s",
  889.            procPtr->processID, 
  890.            procPtr->weightedUsage, 
  891.            userTime.seconds,
  892.            userTime.microseconds,
  893.            kernelTime.seconds, 
  894.            kernelTime.microseconds,
  895.            procPtr->event,
  896.            states[(int) state]);
  897.     if (procPtr->argString != (Address) NIL) {
  898.     char cmd[30];
  899.     char *space;
  900.  
  901.     (void) strncpy(cmd, procPtr->argString, 30);
  902.     space = strchr(cmd, ' ');
  903.     if (space != (char *) NULL) {
  904.         *space = '\0';
  905.     }
  906.     printf(" %s\n", cmd);
  907.     } else {
  908.     printf("\n");
  909.     }
  910. }
  911.  
  912. /*
  913.  *----------------------------------------------------------------------
  914.  *
  915.  * Proc_KillAllProcesses --
  916.  *
  917.  *    Send the kill signal to all processes in the proc table except for
  918.  *    the caller.  If userProcsOnly is TRUE only send signals to user 
  919.  *    processes.
  920.  *
  921.  * Results:
  922.  *    The number of runnable and waiting processes.
  923.  *
  924.  * Side effects:
  925.  *    The kill signal bit is set for all processes.
  926.  *
  927.  *----------------------------------------------------------------------
  928.  */
  929. int
  930. Proc_KillAllProcesses(userProcsOnly)
  931.     Boolean    userProcsOnly;    /* TRUE if only kill user processes. */
  932. {
  933.     register int i;
  934.     register Proc_ControlBlock    *pcbPtr;
  935.     Proc_ControlBlock        *curProcPtr;
  936.     int                alive = 0;
  937.  
  938.     curProcPtr = Proc_GetActualProc();
  939.  
  940.     for (i = 0; i < proc_MaxNumProcesses; i++) {
  941.     pcbPtr = proc_PCBTable[i];
  942.     if (pcbPtr == curProcPtr || pcbPtr->state == PROC_UNUSED ||
  943.         (userProcsOnly && !(pcbPtr->genFlags & PROC_USER))) {
  944.         continue;
  945.     }
  946.     Proc_Lock(pcbPtr);
  947.     if (pcbPtr->state == PROC_RUNNING ||
  948.         pcbPtr->state == PROC_READY ||
  949.         pcbPtr->state == PROC_WAITING ||
  950.         pcbPtr->state == PROC_MIGRATED) {
  951.         alive++;
  952.         (void) Sig_SendProc(pcbPtr, SIG_KILL, 0, (Address)0);
  953.     }
  954.     Proc_Unlock(pcbPtr);
  955.     }
  956.  
  957.     return(alive);
  958. }
  959.  
  960.  
  961. /*
  962.  *----------------------------------------------------------------------
  963.  *
  964.  * Proc_WakeupAllProcesses --
  965.  *
  966.  *    Wakup all waiting processes.
  967.  *
  968.  * Results:
  969.  *    None.
  970.  *
  971.  * Side effects:
  972.  *    All waiting processes are awakened.
  973.  *
  974.  *----------------------------------------------------------------------
  975.  */
  976. void
  977. Proc_WakeupAllProcesses()
  978. {
  979.     register int        i;
  980.     register Proc_ControlBlock    *pcbPtr;
  981.     Proc_ControlBlock        *curProcPtr;
  982.  
  983.     curProcPtr = Proc_GetActualProc();
  984.  
  985.     for (i = 0; i < proc_MaxNumProcesses; i++) {
  986.     pcbPtr = proc_PCBTable[i];
  987.     if (pcbPtr == curProcPtr) {
  988.         continue;
  989.     }
  990.     Proc_Lock(pcbPtr);
  991.     if (pcbPtr->state != PROC_UNUSED) {
  992.         Sync_WakeWaitingProcess(pcbPtr);
  993.     }
  994.     Proc_Unlock(pcbPtr);
  995.     }
  996. }
  997.  
  998.  
  999. /*
  1000.  *----------------------------------------------------------------------
  1001.  *
  1002.  * Proc_HasPermission --
  1003.  *
  1004.  *      See if the current process has permission to perform an operation on
  1005.  *      a process with the given user id.
  1006.  *
  1007.  * Results:
  1008.  *      TRUE if the current process has the same effective user id
  1009.  *      as the given user id or the current process is super user.
  1010.  *
  1011.  * Side effects:
  1012.  *      None.
  1013.  *
  1014.  *----------------------------------------------------------------------
  1015.  */
  1016.  
  1017. Boolean
  1018. Proc_HasPermission(userID)
  1019.     int         userID;
  1020. {
  1021.     Proc_ControlBlock   *procPtr;
  1022.  
  1023.     procPtr = Proc_GetEffectiveProc();
  1024.     return(procPtr->effectiveUserID == userID ||
  1025.            procPtr->effectiveUserID == PROC_SUPER_USER_ID);
  1026. }
  1027.  
  1028.  
  1029.  
  1030. /*
  1031.  *----------------------------------------------------------------------
  1032.  *
  1033.  * Proc_DoForEveryProc --
  1034.  *
  1035.  *    For every process in the process table, apply *booleanFuncPtr to it.
  1036.  *    If that returns TRUE, apply *actionFuncPtr to it.  This is done by
  1037.  *    passing booleanFuncPtr to a monitored routine and having it
  1038.  *    return an array of qualifying processes.  There is a bit of a race
  1039.  *    condition if something happens to any of those processes after the
  1040.  *    list is returned, but in that case the process is ignored and the next
  1041.  *    one is processed.
  1042.  *
  1043.  *    IgnoreStatus indicates whether the routine should abort if
  1044.  *    a non-SUCCESS status is returned by *actionFuncPtr.
  1045.  *
  1046.  * Results:
  1047.  *    If anything "unexpected" happens, FAILURE will be returned, but in
  1048.  *    general SUCCESS is returned.  If numMatchedPtr is non-NIL, then
  1049.  *    the number of processes matched is returned in *numMatchedPtr.
  1050.  *
  1051.  * Side effects:
  1052.  *    The process table is locked temporarily.  Otherwise, dependent on the
  1053.  *    call-back procedures.
  1054.  *
  1055.  *----------------------------------------------------------------------
  1056.  */
  1057.  
  1058. ReturnStatus
  1059. Proc_DoForEveryProc(booleanFuncPtr, actionFuncPtr, ignoreStatus, numMatchedPtr)
  1060.     Boolean (*booleanFuncPtr) _ARGS_((Proc_ControlBlock *pcbPtr));
  1061.                     /* function to match */
  1062.     ReturnStatus (*actionFuncPtr)_ARGS_((Proc_PID pid));    
  1063.                     /* function to invoke on matches */
  1064.     Boolean ignoreStatus;        /* do not abort if bad ReturnStatus  */
  1065.     int *numMatchedPtr;            /* number of matches in table, or NIL */
  1066. {
  1067.     ReturnStatus status = SUCCESS;
  1068.     Proc_PID *pidArray;
  1069.     int max;
  1070.     int i;
  1071.     int numMatched;
  1072.  
  1073.     max = proc_MaxNumProcesses;
  1074.  
  1075.     pidArray = (Proc_PID *) malloc(sizeof(Proc_PID) * max);
  1076.     numMatched = ProcTableMatch(max, booleanFuncPtr, pidArray);
  1077.     for (i = 0; i < numMatched; i++) {
  1078.     status = (*actionFuncPtr)(pidArray[i]);
  1079.     if ((!ignoreStatus) && (status != SUCCESS)) {
  1080.         break;
  1081.     }
  1082.     }
  1083.     free((Address) pidArray);
  1084.     if (numMatchedPtr != (int *) NIL) {
  1085.     *numMatchedPtr = numMatched;
  1086.     }
  1087.     if (ignoreStatus) {
  1088.     return(SUCCESS);
  1089.     }
  1090.     return(status);
  1091. }
  1092.  
  1093.  
  1094. /*
  1095.  *----------------------------------------------------------------------
  1096.  *
  1097.  * Proc_SetServerPriority --
  1098.  *
  1099.  *    Changes the priority of a server process to the non-interruptable
  1100.  *    value. The pid is assumed to be valid.
  1101.  *
  1102.  * Results:
  1103.  *    None.
  1104.  *
  1105.  * Side effects:
  1106.  *    The process's priority is changed.
  1107.  *
  1108.  *----------------------------------------------------------------------
  1109.  */
  1110.  
  1111. void
  1112. Proc_SetServerPriority(pid)
  1113.     Proc_PID    pid;
  1114. {
  1115.     Proc_GetPCB(pid)->billingRate = PROC_NO_INTR_PRIORITY;
  1116. }
  1117.  
  1118.  
  1119.  
  1120. /*
  1121.  *----------------------------------------------------------------------
  1122.  *
  1123.  * Proc_GetHostIDs --
  1124.  *
  1125.  *    Returns the sprite IDs corresponding to the machines on which
  1126.  *    the current process is effectively executing and on which
  1127.  *    it is physically executing.  These hosts are called the virtualHost
  1128.  *    and physicalHost, respectively.  For an unmigrated process, these
  1129.  *    two are identical.
  1130.  *
  1131.  * Results:
  1132.  *    SUCCESS         The call was successful.
  1133.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  1134.  *
  1135.  * Side effects:
  1136.  *    None.
  1137.  *
  1138.  *----------------------------------------------------------------------
  1139.  */
  1140.  
  1141. ReturnStatus
  1142. Proc_GetHostIDs(virtualHostPtr, physicalHostPtr)
  1143.     int    *virtualHostPtr;       /* Buffer to hold virtual host ID. */
  1144.     int    *physicalHostPtr;       /* Buffer to hold physical host ID. */
  1145. {
  1146.  
  1147.     Proc_ControlBlock *procPtr;
  1148.     int host;
  1149.  
  1150.     if (physicalHostPtr != (int *) USER_NIL) {
  1151.  
  1152.     if (Vm_CopyOut(sizeof(int), (Address) &rpc_SpriteID, 
  1153.                 (Address) physicalHostPtr) != SUCCESS) {
  1154.         return(SYS_ARG_NOACCESS);
  1155.     }
  1156.     }
  1157.  
  1158.  
  1159.     if (virtualHostPtr != (int *) USER_NIL) {
  1160.     procPtr = Proc_GetCurrentProc();
  1161.     Proc_Lock(procPtr);
  1162.     host = procPtr->peerHostID;
  1163.     Proc_Unlock(procPtr);
  1164.     if (host == NIL) {
  1165.         host = rpc_SpriteID;
  1166.     }
  1167.     if (Vm_CopyOut(sizeof(int), (Address) &host, 
  1168.                 (Address) virtualHostPtr) != SUCCESS) {
  1169.         return(SYS_ARG_NOACCESS);
  1170.     }
  1171.     }
  1172.  
  1173.     return(SUCCESS);
  1174. }
  1175.  
  1176. /*
  1177.  *----------------------------------------------------------------------
  1178.  *
  1179.  * Proc_PushLockStack --
  1180.  *
  1181.  *    Pushes the given lock type on the lock stack for the process.
  1182.  *
  1183.  * Results:
  1184.  *    None.
  1185.  *
  1186.  * Side effects:
  1187.  *    Stuff is printed if the stack overflows.
  1188.  *
  1189.  *----------------------------------------------------------------------
  1190.  */
  1191.  
  1192. /*ARGSUSED*/
  1193. void
  1194. Proc_PushLockStack(pcbPtr, type, lockPtr)
  1195.     Proc_ControlBlock        *pcbPtr;    /* ptr to pcb to modify */
  1196.     int                type;        /* type of lock */
  1197.     Address            lockPtr;    /* ptr to lock */
  1198.  
  1199. {
  1200. #ifdef LOCKDEP
  1201.     static Boolean    firstOverflow = TRUE;
  1202.  
  1203.     /*
  1204.      *  Modifying the lock stack of a process has to be an atomic operation,
  1205.      *  but we don't want to use a lock to do this, since this is part of
  1206.      *  the code used when locking or unlocking. Using a lock would lead
  1207.      *  to a circularity and probably a deadlock. All we really need to
  1208.      *  prevent is an interrupt handler from grabbing a lock while we're
  1209.      *  modifying the lock stack. A process only modifies its own
  1210.      *  lock stack, so turning off interrupts should be good enough.
  1211.      */
  1212.     DISABLE_INTR();
  1213.     if (pcbPtr->lockStackSize >= PROC_LOCKSTACK_SIZE) {
  1214.     if (firstOverflow) {
  1215.         printf("Proc_PushLockStack: stack overflow in pcb 0x%x.\n",pcbPtr);
  1216.         firstOverflow = FALSE;
  1217.     }
  1218.     goto exit;
  1219.     }
  1220.     if (pcbPtr->lockStackSize < 0 ) {
  1221.     printf("Proc_PushLockStack: stack underflow (%d) in pcb 0x%x.\n",
  1222.            pcbPtr->lockStackSize, pcbPtr);
  1223.         goto exit;
  1224.     }
  1225.     pcbPtr->lockStack[pcbPtr->lockStackSize].type = type;
  1226.     pcbPtr->lockStack[pcbPtr->lockStackSize].lockPtr = lockPtr;
  1227.     pcbPtr->lockStackSize++;
  1228. exit:
  1229.     ENABLE_INTR();
  1230. #endif
  1231. }
  1232.  
  1233. /*
  1234.  *----------------------------------------------------------------------
  1235.  *
  1236.  * Proc_RemoveFromLockStack --
  1237.  *
  1238.  *    Removes the given lock from the stack if it is there.
  1239.  *
  1240.  * Results:
  1241.  *    None.
  1242.  *
  1243.  * Side effects:
  1244.  *    None.
  1245.  *
  1246.  *----------------------------------------------------------------------
  1247.  */
  1248.  
  1249. /*ARGSUSED*/
  1250. void
  1251. Proc_RemoveFromLockStack(pcbPtr, lockPtr)
  1252.     Proc_ControlBlock        *pcbPtr;    /* ptr to pcb to modify */
  1253.     Address            lockPtr;    /* ptr to lock */
  1254. {
  1255. #ifdef LOCKDEP
  1256.     int     i;
  1257.     int        stackTop;
  1258.     Boolean     found = FALSE;
  1259.  
  1260.     DISABLE_INTR();
  1261.     if (pcbPtr->lockStackSize < 0) {
  1262.     ENABLE_INTR();
  1263.     panic("Lock stack underflow (1).\n");
  1264.     goto exit;
  1265.     }
  1266.     if (pcbPtr->lockStackSize == 0) {
  1267.     goto exit;
  1268.     }
  1269.     stackTop = pcbPtr->lockStackSize - 1;
  1270.     for (i = pcbPtr->lockStackSize - 1; i >= 0; i--) {
  1271.     if (pcbPtr->lockStack[i].lockPtr == lockPtr) {
  1272.         pcbPtr->lockStack[i].lockPtr = (Address) NIL;
  1273.         pcbPtr->lockStack[i].type = -1;
  1274.         found = TRUE;
  1275.         break;
  1276.     }
  1277.     }
  1278.     if (!found) {
  1279.     goto exit;
  1280.     }
  1281.     for (i = stackTop; i >= 0; i--) {
  1282.     if (pcbPtr->lockStack[i].lockPtr != (Address) NIL) {
  1283.         break;
  1284.     }
  1285.     }
  1286.     pcbPtr->lockStackSize = i + 1;
  1287.     if (pcbPtr->lockStackSize < 0) {
  1288.     printf("lockStackSize %d\n",pcbPtr->lockStackSize);
  1289.     }
  1290. exit:
  1291.     ENABLE_INTR();
  1292. #endif
  1293. }
  1294.  
  1295. #ifndef LOCKREG
  1296. #ifndef CLEAN_LOCK
  1297. #ifndef CLEAN
  1298. /*
  1299.  *----------------------------------------------------------------------
  1300.  *
  1301.  * Proc_KDump --
  1302.  *
  1303.  *    Prints out an (kluged) proc table with state information.
  1304.  *
  1305.  *    This routine uses several macros to analyse the event data structure:
  1306.  *    ISADDR(x) tests if x is a valid address.
  1307.  *    ISSTR(x) tests if x is a pointer to a valid string.
  1308.  *    ISALIGN(x) tests if x is an aligned address.
  1309.  *    ISBOOL(x) tests if x is a boolean.
  1310.  *    ISSMALL(x) tests is x is a small integer.
  1311.  *    ISLIST(x) tests if x points to a List_Links structure.
  1312.  *    ISPCB(x) tests if x points to a Proc_ControlBlock structure.
  1313.  *    FIELD(x,type,field) is x->type.field
  1314.  *
  1315.  * Results:
  1316.  *    SUCCESS.
  1317.  *
  1318.  * Side effects:
  1319.  *    Prints stuff to screen.
  1320.  *
  1321.  *
  1322.  *----------------------------------------------------------------------
  1323.  */
  1324. #define INT(x)        ((int)(x))
  1325. #define INTP(x)        ((int *)(x))
  1326. #define    ISSTRZ(x)    (INT(x)==0 || ISSTR(x))
  1327. #define ISALIGN(x)    (ISADDR(x) && (INT(x)&3)==0)
  1328. #define ISALIGNZ(x)    (INT(x)==0 || INT(x)==NIL || ISALIGN(x))
  1329. /* sun3 test-and-set sets to 0x80000000, sun4 to 0xff000000 */
  1330. #define ISBOOL(x)    (INT(x)==0||INT(x)==1||INT(x)==0x80000000||\
  1331.             INT(x)==0xff000000)
  1332. #define ISSMALL(x)    (INT(x)>=0&&INT(x)<20)
  1333. #define ISPCBZ(x)    (INT(x)==0||INT(x)==NIL||ISPCB(x))
  1334. #define OFF(type,field) (INTP(&(((type *)0)->field))-INTP(0))
  1335. #define READIN(type,src,dst) (READIN_INT(sizeof(type),(Address)(src),\
  1336.         (Address)(dst)))
  1337.  
  1338. static int ISADDR _ARGS_((Address x));
  1339. static int ISSTR _ARGS_((char *x));
  1340. static int PRINTHANDLE _ARGS_ ((char *str, Fs_HandleHeader *handlePtr));
  1341. static int ISLIST _ARGS_((List_Links *x));
  1342. static int ISPCB _ARGS_((Proc_ControlBlock *x));
  1343. static int FINDPID _ARGS_((Proc_ControlBlock *x));
  1344. static int PRINTRPCCLIENT _ARGS_((RpcClientChannel *x));
  1345. static int PRINTRPCSERVER _ARGS_((RpcServerState *x));
  1346. static int PRINTSERVERPROC _ARGS_((ServerInfo *x));
  1347. static int PRINTLOCK _ARGS_((Sync_Lock *x, int print));
  1348. static int PRINTSEM _ARGS_((Sync_Semaphore *x));
  1349. static int PRINTLFS _ARGS_((Lfs *x, char *text));
  1350.  
  1351. /*
  1352.  * Read in some memory.
  1353.  * The macro looks after the types.
  1354.  */
  1355. static int READIN_INT(len,src,dst)
  1356. int len;
  1357. Address src,dst;
  1358. {
  1359.     ReturnStatus status;
  1360.     int i;
  1361. #if defined(ds3100) || defined(ds5000)
  1362.     /* Mach_Probe doesn't work right for some reason */
  1363.     char buf[2];
  1364.     for (i=0;i<len;i++) {
  1365.     if (! Dbg_InRange(((unsigned)src)&~1,2,FALSE)) {
  1366.         return FALSE;
  1367.     }
  1368.     }
  1369.     bcopy(src,dst,len);
  1370.     return TRUE;
  1371. #else
  1372.     for (i=0;i<len;i++) {
  1373.     status = Mach_Probe(1,src+i,dst+i);
  1374.     if (status != SUCCESS) return FALSE;
  1375.     }
  1376.     return TRUE;
  1377. #endif
  1378. }
  1379.  
  1380. /*
  1381.  * Test if x is a valid address.
  1382.  */
  1383. static int ISADDR(x)
  1384. Address x;
  1385. {
  1386.     int buf;
  1387.     if (READIN(int,x,(Address)&buf)) {
  1388.     return TRUE;
  1389.     } else {
  1390.     return FALSE;
  1391.     }
  1392. }
  1393.  
  1394. /*
  1395.  * Test if x is a string.  Leave the string in strbuf if so.
  1396.  */
  1397. char strbuf[40];
  1398. static int ISSTR(x)
  1399. char *x;
  1400. {
  1401.     int i;
  1402.     for (i=0;i<sizeof(strbuf);i++) {
  1403.     if (!READIN(char,x+i,strbuf+i)) {
  1404.         return FALSE;
  1405.     }
  1406.     if (strbuf[i]=='\0') {
  1407.         return TRUE;
  1408.     }
  1409.     if (!isprint(strbuf[i])) {
  1410.         return FALSE;
  1411.     }
  1412.     }
  1413.     strbuf[39]='\0';
  1414.     return TRUE;
  1415. }
  1416.  
  1417.  
  1418. /*
  1419.  * Print out the name associated with a handle.
  1420.  */
  1421. static int PRINTHANDLE(str,handlePtr)
  1422. char *str;
  1423. Fs_HandleHeader *handlePtr;
  1424. {
  1425.     Fs_HandleHeader handle;
  1426.     if (!READIN(Fs_HandleHeader,handlePtr,&handle) ||
  1427.         !ISLIST(&handle.lruLinks) || !ISBOOL(handle.unlocked.waiting) ||
  1428.         !ISSMALL(handle.refCount) ||
  1429.         !(handle.lockProcPtr==(Proc_ControlBlock *)NIL ||
  1430.         ISPCB(handle.lockProcPtr))) {
  1431.     return FALSE;
  1432.     }
  1433.     if (handle.name==(char *)NIL) {
  1434.     printf("%s: \"%s\" (handle locked by %x)", str, "(no name)",
  1435.         handle.lockProcPtr);
  1436.     } else if (ISSTR(handle.name)) {
  1437.     printf("%s: \"%s\" (handle locked by %x)", str, strbuf,
  1438.         handle.lockProcPtr);
  1439.     } else {
  1440.     printf("%s: \"%s\" (handle locked by %x)", str, "(bad name)",
  1441.         handle.lockProcPtr);
  1442.     }
  1443.     return TRUE;
  1444. }
  1445.  
  1446. /*
  1447.  * Test if x is a list.
  1448.  */
  1449. static int ISLIST(x)
  1450. List_Links *x;
  1451. {
  1452.     List_Links thisList, prevList, nextList;
  1453.     int retVal;
  1454.     retVal =  READIN(List_Links,x,&thisList) &&
  1455.         READIN(List_Links,thisList.prevPtr,&prevList) &&
  1456.         READIN(List_Links,thisList.nextPtr,&nextList) &&
  1457.         prevList.nextPtr == x && nextList.prevPtr == x;
  1458.     return retVal;
  1459. }
  1460.  
  1461. /*
  1462.  * Test if x is a pcb
  1463.  */
  1464. static int ISPCB(x)
  1465. Proc_ControlBlock *x;
  1466. {
  1467.     Proc_ControlBlock pcb;
  1468.     int retVal;
  1469.     retVal = READIN(Proc_ControlBlock,x,&pcb) && ISSMALL(pcb.processor) &&
  1470.             ISSTR(pcb.argString) && ISADDR((Address)pcb.links.prevPtr) &&
  1471.         ISADDR((Address)pcb.links.nextPtr) && ISSMALL(pcb.state) &&
  1472.         ISADDR((Address)pcb.childList) && pcb.processID <=0xfffff;
  1473. #if 0
  1474.     if (!retVal) {
  1475.         if (!READIN(Proc_ControlBlock,x,&pcb)) {
  1476.         printf("PCB: READIN failed ");
  1477.     } else if (!ISLIST(&pcb.links)) {
  1478.         printf("PCB: LIST failed ");
  1479.     } else if (!ISSMALL(pcb.processor)) {
  1480.         printf("PCB: SMALL failed ");
  1481.     } else if (!ISLIST(&pcb.childListHdr)) {
  1482.         printf("PCB: LIST2 failed ");
  1483.     } else if (pcb.processID >0xfffff) {
  1484.     } else {
  1485.         printf("PCB: mystery ");
  1486.     }
  1487.     }
  1488. #endif
  1489.     return retVal;
  1490. }
  1491.  
  1492. /*
  1493.  * Return PID or 0
  1494.  */
  1495. static int FINDPID(x)
  1496. Proc_ControlBlock *x;
  1497. {
  1498.     Proc_ControlBlock pcb;
  1499.     if (READIN(Proc_ControlBlock,x,&pcb) && ISPCB(&pcb)) {
  1500.     return pcb.processID;
  1501.     } else {
  1502.     return FALSE;
  1503.     }
  1504. }
  1505.  
  1506. /*
  1507.  * Print if x is a rpc client channel
  1508.  */
  1509. static int PRINTRPCCLIENT(x)
  1510. RpcClientChannel *x;
  1511. {
  1512.     int i;
  1513.     RpcClientChannel chan;
  1514.     if (!READIN(RpcClientChannel,x,&chan)) {
  1515.     return FALSE;
  1516.     }
  1517.     for (i=0;i<rpcNumChannels;i++) {
  1518.     if (rpcChannelPtrPtr[i] == x) {
  1519.         printf("RPC client: \"waitCondition\", server %d ",
  1520.             chan.serverID);
  1521.         if (chan.state & CHAN_FREE) {
  1522.         printf("FREE ");
  1523.         }
  1524.         if (chan.state & CHAN_BUSY) {
  1525.         printf("BUSY ");
  1526.         }
  1527.         if (chan.state & CHAN_WAITING) {
  1528.         printf("WAIT ");
  1529.         }
  1530.         if (chan.state & CHAN_TIMEOUT) {
  1531.         printf("TIME ");
  1532.         }
  1533.         if (chan.state & CHAN_FRAGMENTING) {
  1534.         printf("FRAG ");
  1535.         }
  1536.         return TRUE;
  1537.     }
  1538.     }
  1539.     return FALSE;
  1540. }
  1541.  
  1542. /*
  1543.  * Test if x is a rpc server.
  1544.  */
  1545. static int PRINTRPCSERVER(x)
  1546. RpcServerState *x;
  1547. {
  1548.     int i;
  1549.     RpcServerState state;
  1550.     if (!READIN(RpcServerState,x,&state)) {
  1551.     return FALSE;
  1552.     }
  1553.     for (i=0;i<rpcMaxServers;i++) {
  1554.     if (rpcServerPtrPtr[i] == x) {
  1555.         printf("RPC server:\"waitCondition\", client %d ",
  1556.             state.clientID);
  1557.         if (state.state & SRV_NOTREADY) {
  1558.         printf("NOTREADY ");
  1559.         }
  1560.         if (state.state & SRV_FREE) {
  1561.         printf("FREE ");
  1562.         }
  1563.         if (state.state & SRV_BUSY) {
  1564.         printf("BUSY ");
  1565.         }
  1566.         if (state.state & SRV_WAITING) {
  1567.         printf("WAIT ");
  1568.         }
  1569.         if (state.state & SRV_AGING) {
  1570.         printf("AGING ");
  1571.         }
  1572.         if (state.state & SRV_FRAGMENT) {
  1573.         printf("FRAG ");
  1574.         }
  1575.         if (state.state & SRV_NO_REPLY) {
  1576.         printf("NO_REPLY ");
  1577.         }
  1578.         if (state.state & SRV_STUCK) {
  1579.         printf("STUCK ");
  1580.         }
  1581.         return TRUE;
  1582.     }
  1583.     }
  1584.     return FALSE;
  1585. }
  1586.  
  1587. /* 
  1588.  * Print if x is a rpc server proc
  1589.  */
  1590. static int PRINTSERVERPROC(x)
  1591. ServerInfo *x;
  1592. {
  1593.     int i;
  1594.     ServerInfo info;
  1595.     if (!READIN(ServerInfo,x,&info)) {
  1596.     return FALSE;
  1597.     }
  1598.     for (i=0;i<proc_NumServers;i++) {
  1599.     if (serverInfoTable+i == x) {
  1600.         printf("ServerProc: \"condition\" (waiting for task)");
  1601.         if (info.flags & SERVER_BUSY) {
  1602.         printf("BUSY ");
  1603.         }
  1604.         if (info.flags & FUNC_PENDING) {
  1605.         printf("PENDING ");
  1606.         }
  1607.         return TRUE;
  1608.     }
  1609.     }
  1610.     return FALSE;
  1611. }
  1612.  
  1613. /*
  1614.  * Print if x is a Lfs structure
  1615.  */
  1616. static int PRINTLFS(x, text)
  1617. Lfs *x;
  1618. char *text;
  1619. {
  1620.     Lfs lfs;
  1621.     if (!READIN(Lfs,x,&lfs)) {
  1622.     return FALSE;
  1623.     }
  1624.     if (ISSTR(lfs.name) && ISBOOL(lfs.writeBackActive) &&
  1625.         PRINTLOCK(&lfs.cacheBackendLock,0) &&
  1626.         ISBOOL(lfs.writeBackMoreWork) && ISBOOL(lfs.shutDownActive) &&
  1627.         PRINTLOCK(&lfs.lock,0)) {
  1628.     (void) ISSTR(lfs.name);
  1629.     printf("Lfs: %s on %s", text, strbuf);
  1630.     return TRUE;
  1631.     }
  1632.     return FALSE;
  1633. }
  1634.  
  1635. /*
  1636.  * Print if x is a lock.
  1637.  * Or just return true/false if print=0;
  1638.  */
  1639. static int PRINTLOCK(x,print)
  1640. Sync_Lock *x;
  1641. int print;
  1642. {
  1643.     Sync_Lock lock;
  1644.     if (READIN(Sync_Lock,x,&lock) && ISBOOL(lock.inUse) &&
  1645.         ISBOOL(lock.waiting) &&
  1646.         ISALIGNZ(lock.holderPC) && ISPCBZ(lock.holderPCBPtr) &&
  1647.         ISSTR(lock.name)) {
  1648.     if (print) {
  1649.         printf("lock \"%s\" at %x", strbuf, lock.holderPC);
  1650.     }
  1651.     if (print && FINDPID(lock.holderPCBPtr)) {
  1652.         printf(" held by process %x", FINDPID(lock.holderPCBPtr));
  1653.     }
  1654.     return TRUE;
  1655.     } else {
  1656.     return FALSE;
  1657.     }
  1658. }
  1659.  
  1660. /*
  1661.  * Test if x is a semaphore.
  1662.  */
  1663. static int PRINTSEM(x)
  1664. Sync_Semaphore *x;
  1665. {
  1666.     Sync_Semaphore sem;
  1667.     if (READIN(Sync_Semaphore,x,&sem) && ISSMALL(sem.value) &&
  1668.         ISALIGNZ(sem.holderPC) &&
  1669.         ISPCBZ(sem.holderPCBPtr) && ISSTR(sem.name)) {
  1670.     printf("semaphore \"%s\" at %x", strbuf, sem.holderPC);
  1671.     if (FINDPID(sem.holderPCBPtr)) {
  1672.         printf(" held by process %x",
  1673.             FINDPID(sem.holderPCBPtr));
  1674.     }
  1675.     return TRUE;
  1676.     } else {
  1677.     return FALSE;
  1678.     }
  1679. }
  1680.  
  1681. typedef struct LockEntry {
  1682.     int    addr;        /* Address (event) associated with the lock. */
  1683.     char *name;        /* Name of the lock event. */
  1684. } LockEntry;
  1685.  
  1686. extern Sync_Condition cleanBlockCondition, writeBackComplete,
  1687.     closeCondition, lruDone, debugListCondition, familyCondition,
  1688.     migrateCondition, evictCondition, recovCondition, recovPingCondition,
  1689.     rpcDaemon, freeChannels, signalCondition, codeSegCondition,
  1690.     cleanCondition, swapDownCondition, mappingCondition, swapFileCondition;
  1691.  
  1692. LockEntry locks[] = {
  1693.     (int)&cleanBlockCondition, "cleanBlockCondition",
  1694.     (int)&writeBackComplete, "writeBackComplete",
  1695.     (int)&closeCondition, "closeCondition",
  1696.     (int)&lruDone, "lruDone",
  1697.     (int)&debugListCondition, "debugListCondition",
  1698.     (int)&familyCondition, "familyCondition",
  1699.     (int)&migrateCondition, "migrateCondition",
  1700.     (int)&evictCondition, "evictCondition",
  1701.     (int)&recovCondition, "recovCondition",
  1702.     (int)&rpcDaemon, "rpcDaemon",
  1703.     (int)&freeChannels, "freeChannels",
  1704.     (int)&signalCondition, "signalCondition (pause syscall)",
  1705.     (int)&codeSegCondition, "codeSegCondition",
  1706.     (int)&cleanCondition, "cleanCondition",
  1707.     (int)&swapDownCondition, "swapDownCondition",
  1708.     (int)&mappingCondition, "mappingCondition",
  1709.     (int)&swapFileCondition, "swapFileCondition",
  1710.     (int)&recovPingCondition, "recovPingCondition",
  1711.     0, 0
  1712. };
  1713.  
  1714. static void Proc_KDumpInt _ARGS_((ClientData data, Proc_CallInfo *callInfoPtr));
  1715.  
  1716. void
  1717. Proc_KDump(data)
  1718.     ClientData data;
  1719. {
  1720.     Proc_CallFunc(Proc_KDumpInt, data, 0);
  1721. }
  1722.  
  1723. /*ARGSUSED*/
  1724. static void
  1725. Proc_KDumpInt(data, callInfoPtr)
  1726.     ClientData    data;
  1727.     Proc_CallInfo *callInfoPtr;
  1728. {
  1729.     int i;
  1730.     Proc_ControlBlock *procPtr, *tmpProcPtr;
  1731.     int *event;
  1732.     int atEvent;
  1733.     LockEntry *lockPtr;
  1734.     Fscache_FileInfo cacheInfo, *cacheInfoPtr;
  1735.     Fs_HandleHeader *handlePtr;
  1736.     RpcClientChannel *rpcClientPtr;
  1737.     RpcServerState *rpcServerPtr;
  1738.     ServerInfo *serverProcPtr;
  1739.     Sync_Lock *syncLockPtr;
  1740.     Fsconsist_Info consistInfo;
  1741.     Lfs *lfsPtr;
  1742.     int match;
  1743.  
  1744.     for (i = 0; i < proc_MaxNumProcesses; i++) {
  1745.     procPtr = proc_PCBTable[i];
  1746.     match = 0;
  1747.     if (procPtr->state == PROC_WAITING) {
  1748.         printf("%6x", procPtr->processID);
  1749.         if (procPtr->argString != (Address) NIL) {
  1750.         char cmd[30];
  1751.         char *space;
  1752.  
  1753.         (void) strncpy(cmd, procPtr->argString, 30);
  1754.         space = strchr(cmd, ' ');
  1755.         if (space != (char *) NULL) {
  1756.             *space = '\0';
  1757.         } else {
  1758.             cmd[29] = '\0';
  1759.         }
  1760.         printf("(%s)", cmd);
  1761.         }
  1762.         printf(": ");
  1763.         event = (int *)procPtr->event;
  1764.         if (ISADDR((Address)event)) {
  1765.         for (lockPtr = locks ; lockPtr->addr != 0; lockPtr++) {
  1766.             if ((int)event == lockPtr->addr) {
  1767.             printf("condition \"%s\"\n", lockPtr->name);
  1768.             goto found;
  1769.             }
  1770.         }
  1771.         if (PRINTLOCK((Sync_Lock *)event,1)) {
  1772.             /* Sync_Lock / Sync_KernelLock */
  1773.         } else if ((Proc_ControlBlock *)event==procPtr) {
  1774.             /* Proc_ControlBlock */
  1775.             printf("timer");
  1776.         } else if (FINDPID((Proc_ControlBlock *)event)) {
  1777.             /* Proc_ControlBlock */
  1778.             printf("timer %x", FINDPID((Proc_ControlBlock *)event));
  1779.         } else if (PRINTSEM((Sync_Semaphore *)event)) {
  1780.            /* Sync_Semaphore */
  1781.         } else if (READIN(int,event,&atEvent) && ISBOOL(atEvent)) {
  1782.             /* Sync_Condition */
  1783.             handlePtr = (Fs_HandleHeader *)
  1784.                 (event-OFF(Fs_HandleHeader,unlocked));
  1785.             if (PRINTHANDLE("handle: \"unlocked\"", handlePtr)) {
  1786.             match++;
  1787.             }
  1788.             /*
  1789.              * We might be blocked on the noDirtyBlocks field of
  1790.              * a Fscache_FileInfo structure.  In that case, print
  1791.              * the associated handle.
  1792.              */
  1793.             if (READIN(Fs_HandleHeader *,((int *)event)-
  1794.                 OFF(Fscache_FileInfo,noDirtyBlocks)+
  1795.                 OFF(Fscache_FileInfo,hdrPtr),&handlePtr)) {
  1796.             if (PRINTHANDLE("cache block: \"noDirtyBlocks\"",
  1797.                     handlePtr)) {
  1798.                 match++;
  1799.             }
  1800.             }
  1801.             /*
  1802.              * We might be blocked on the ioDone field of a
  1803.              * Fscache_Block structure.  In that case, access the
  1804.              * cacheInfoPtr and print the handle.
  1805.              */
  1806.             if (READIN(Fscache_FileInfo *,((int *)event)-
  1807.                 OFF(Fscache_Block,ioDone)+
  1808.                 OFF(Fscache_Block,cacheInfoPtr),&cacheInfoPtr)) {
  1809.             if (READIN(Fscache_FileInfo,cacheInfoPtr,&cacheInfo) &&
  1810.                 PRINTHANDLE("cache block: \"ioDone\"",
  1811.                     cacheInfo.hdrPtr)) {
  1812.                 match++;
  1813.             }
  1814.             }
  1815.             /*
  1816.              * We might be blocked on the waitCondition in the PCB.
  1817.              */
  1818.             tmpProcPtr = (Proc_ControlBlock *)
  1819.                 (event-OFF(Proc_ControlBlock,waitCondition));
  1820.             if (tmpProcPtr == procPtr) {
  1821.             printf("PCB: \"waitCondition\" (wait syscall) ");
  1822.             match++;
  1823.             } else if (FINDPID(tmpProcPtr)) {
  1824.             printf("PCB: \"waitCondition\" %x (wait syscall) ",
  1825.                 FINDPID(tmpProcPtr));
  1826.             match++;
  1827.             }
  1828.             /* Or we might be blocked on the lockedCondition */
  1829.             tmpProcPtr = (Proc_ControlBlock *)
  1830.                 (event-OFF(Proc_ControlBlock,lockedCondition));
  1831.             if (tmpProcPtr==procPtr) {
  1832.             printf("PCB: \"lockedCondition\" (locked entry) ");
  1833.             match++;
  1834.             } else if (FINDPID(tmpProcPtr)) {
  1835.             printf("PCB: \"lockedCondition\" %x (locked entry) ",
  1836.                 FINDPID(tmpProcPtr));
  1837.             match++;
  1838.             }
  1839.             /* Or we might be blocked on Fsconsist_Info */
  1840.             syncLockPtr = (Sync_Lock *)(event-
  1841.                 OFF(Fsconsist_Info,consistDone));
  1842.             if (PRINTLOCK(syncLockPtr,1)) {
  1843.             printf(" (consistDone)\n");
  1844.             match++;
  1845.             if (READIN(Fsconsist_Info,syncLockPtr,&consistInfo)) {
  1846.                 (void) PRINTHANDLE("handle:", consistInfo.hdrPtr);
  1847.             }
  1848.             }
  1849.             syncLockPtr = (Sync_Lock *)(event-
  1850.                 OFF(Fsconsist_Info,repliesIn));
  1851.             if (PRINTLOCK(syncLockPtr,1)) {
  1852.             printf(" (repliesIn)\n");
  1853.             match++;
  1854.             if (READIN(Fsconsist_Info,syncLockPtr,&consistInfo)) {
  1855.                 (void) PRINTHANDLE("handle:", consistInfo.hdrPtr);
  1856.             }
  1857.             }
  1858.  
  1859.             /* Maybe it's a LFS structure */
  1860.             lfsPtr = (Lfs *)(event-OFF(Lfs, writeWait));
  1861.             if (PRINTLFS(lfsPtr, "writeWait")) {
  1862.             match++;
  1863.             }
  1864.             lfsPtr = (Lfs *)(event-OFF(Lfs, cleanSegmentsWait));
  1865.             if (PRINTLFS(lfsPtr, "cleanSegmentsWait")) {
  1866.             match++;
  1867.             }
  1868.             lfsPtr = (Lfs *)(event-OFF(Lfs, cacheBackendLock));
  1869.             if (PRINTLFS(lfsPtr, "cacheBackendLock")) {
  1870.             match++;
  1871.             }
  1872.             lfsPtr = (Lfs *)(event-OFF(Lfs, lock));
  1873.             if (PRINTLFS(lfsPtr, "Lfs master lock")) {
  1874.             match++;
  1875.             }
  1876.             lfsPtr = (Lfs *)(event-OFF(Lfs, checkPointWait));
  1877.             if (PRINTLFS(lfsPtr, "checkPointWait")) {
  1878.             match++;
  1879.             }
  1880.  
  1881.             /* Or maybe something else. */
  1882.             serverProcPtr = (ServerInfo *)(event-
  1883.                 OFF(ServerInfo, condition));
  1884.             if (PRINTSERVERPROC(serverProcPtr)) {
  1885.             match++;
  1886.             }
  1887.             rpcClientPtr = (RpcClientChannel *)(event-
  1888.                 OFF(RpcClientChannel, waitCondition));
  1889.             if (PRINTRPCCLIENT(rpcClientPtr)) {
  1890.             match++;
  1891.             }
  1892.             rpcServerPtr = (RpcServerState *)(event-
  1893.                 OFF(RpcServerState, waitCondition));
  1894.             if (PRINTRPCSERVER(rpcServerPtr)) {
  1895.             match++;
  1896.             }
  1897.             handlePtr = (Fs_HandleHeader *)(event-OFF(Fsrmt_IOHandle,
  1898.             recovery.reopenComplete));
  1899.             if (PRINTHANDLE("\"recovery.reopenComplete\"", handlePtr)) {
  1900.             match++;
  1901.             }
  1902.             if (!match) {
  1903.             printf("condition %x", (int)event);
  1904.             } else if (match>1) {
  1905.             printf("(Ambiguous)");
  1906.             }
  1907.         } else {
  1908.             printf("event %x", (int)event);
  1909.         }
  1910.         } else if ((int)event == -1) {
  1911.         printf("wakeup signal (prob. select syscall)");
  1912.         } else {
  1913.         printf("event? %x", (int)event);
  1914.         }
  1915.         printf("\n");
  1916. found:;
  1917.     }
  1918.     }
  1919. }
  1920. #define KDUMP
  1921. #endif
  1922. #endif
  1923. #endif
  1924.  
  1925. #ifndef KDUMP
  1926. /* ARGSUSED */
  1927. ReturnStatus
  1928. Proc_KDump(dummy) 
  1929.     ClientData dummy;
  1930.     return SUCCESS;
  1931. }
  1932. #endif
  1933.